package com.yc.pay.service.impl;

import com.yc.pay.api.resp.YcPayNotifyData;
import com.yc.pay.config.MqConfig;
import com.yc.pay.config.YcPayConfig;
import com.yc.pay.customer.MyMessagePostProcessor;
import com.yc.pay.model.MchInfo;
import com.yc.pay.model.PaySerial;
import com.yc.pay.service.IMchService;
import com.yc.pay.service.INotifyPayService;
import com.yc.pay.service.IPayNoticeService;
import com.yc.pay.service.IPaySerialService;
import com.yc.pay.utils.PayDigestUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

@Service
public class NotifyPayServiceImpl implements INotifyPayService {

    @Autowired
    private IPaySerialService paySerialService;

    private static final Logger logger = LoggerFactory.getLogger(NotifyPayServiceImpl.class);

    @Autowired
    private YcPayConfig ycPayConfig;


    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private IPayNoticeService payNoticeService;

    @Autowired
    private IMchService mchService;



    @Override
    public String notify(Map<String, String> params) {

        //1. 商户需要验证该通知数据中的 out_trade_no 是否为商户系统中创建的订单号；

        String outTradeNo = params.get("out_trade_no");

        PaySerial paySerial = paySerialService.queryByOutTradeNo(outTradeNo);
        if (ObjectUtils.isEmpty(paySerial)){
            logger.info("支付宝返回的商户流水号:{}在数据库中没有找到",outTradeNo);
            return "fail";
        }

        //2.判断 total_amount 是否确实为该订单的实际金额（即商户订单创建时的金额）；

       String totalAmount = params.get("total_amount");

        if (!totalAmount.equals(paySerial.getPayAmt().toString())){
            logger.info("支付宝返回的商户流水号:{}和数据库中的金额不匹配",outTradeNo);
            return "fail";
        }


        //3.校验通知中的 seller_id（或者 seller_email) 是否为 out_trade_no 这笔单据的对应的操作方（有的时候，一个商户可能有多个 seller_id/seller_email）；
        String sellerId = params.get("seller_id");
        if (!sellerId.equals(ycPayConfig.getSellerId())){
            logger.info("支付宝返回的商户流水号:{}sellerId和配置文件中的不匹配",outTradeNo);
            return "fail";
        }

        //4.验证 app_id 是否为该商户本身。
        String appId = params.get("app_id");
        if (!appId.equals(ycPayConfig.getAppId())){
            logger.info("支付宝返回的商户流水号:{}appId和配置文件中的不匹配",outTradeNo);
            return "fail";
        }

        //更新流水
        String tradeStatus = params.get("trade_status");
        Date date = new Date();
        if("TRADE_FINISHED".equals(tradeStatus) || "TRADE_SUCCESS".equals(tradeStatus)){
            //更新为成功 TODO
            PaySerial record = new PaySerial();

            record.setId(paySerial.getId());

            record.setBankRespNo(Integer.parseInt(params.get("trade_no")));
            record.setBankRespMsg("交易成功");
            record.setStatus("0");

            String gmtPayment = params.get("gmt_payment");

            try {
                Date gmtPaymentDate = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss").parse(gmtPayment);
                record.setPaySuccessTime(gmtPaymentDate);
            } catch (ParseException e) {
               logger.error("ParseException",e);
            }
            record.setUpdateTime(date);

            paySerialService.updatePaySerial(record);

            //发送异步通知
            sendNotifyPayResult(record);

            return "success";

        } else if("TRADE_CLOSED".equals(tradeStatus)){
            //更新为失败 TODO
            PaySerial record = new PaySerial();

            record.setBankRespMsg("交易失败:"+ tradeStatus);
            record.setStatus("-1");
            record.setUpdateTime(date);
            paySerialService.updatePaySerial(record);

            //发送异步通知
            sendNotifyPayResult(record);

            return "success";

        }else{
            logger.info("########状态为：{},暂时不处理#########",tradeStatus);
            return "fail";

        }


    }

    /**
     * 发送异步通知
     */
    private void sendNotifyPayResult( PaySerial record ){



        YcPayNotifyData ycPayNotifyData = new YcPayNotifyData();
        ycPayNotifyData.setAmount(record.getPayAmt().toString());
        ycPayNotifyData.setStatus(record.getStatus());
        ycPayNotifyData.setPaySerialNo(record.getPaySerialNo());
        ycPayNotifyData.setMchOrderNo(record.getMchOrderId());

        MchInfo mchInfo = mchService.queryByMchId("1001");

        String sign = null;
        try {
            sign = PayDigestUtil.getSign(ycPayNotifyData,mchInfo.getRespKey());
            ycPayNotifyData.setSign(sign);

        } catch (IllegalAccessException e) {
            logger.error("IllegalAccessException",e);
        }


        //立马通知
        String rlt = restTemplate.postForObject(ycPayConfig.getMchNotifyUrl(),ycPayNotifyData,String.class);

        if ("success".equals(rlt)){
            //业务系统 返回success，创建成功的通知
            payNoticeService.createPayNotice(ycPayNotifyData.getPaySerialNo(),"0");
            return;
        }

        //没有收到success 更新次数
        payNoticeService.upatePayNotice(ycPayNotifyData.getPaySerialNo(),"1");
        MessagePostProcessor myMessagePostProcessor = new MyMessagePostProcessor(30000);
        rabbitTemplate.convertAndSend(MqConfig.BUSINESS_EXCHANGE_NAME,"",ycPayNotifyData,myMessagePostProcessor);

    }
}
